use clap::{Parser, ValueEnum};
use sql2doc_core::{run, ExportType, SqlConfig, SqlType};

#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
    #[arg(long)]
    host: String,
    #[arg(long)]
    port: Option<u16>,
    #[arg(short, long)]
    user: String,
    #[arg(short, long)]
    password: String,
    #[arg(short, long)]
    database: String,
    #[arg(short, long)]
    output: Option<String>,
    #[arg(short, long, value_enum,default_value_t = SqlEnum::Mysql)]
    r#type: SqlEnum,
    #[arg(short,long,value_enum,default_value_t = ExportEnum::Docx)]
    export: ExportEnum,
}

#[derive(Debug, Clone, Copy, ValueEnum, Default)]
enum ExportEnum {
    #[default]
    Docx,
    Markdown,
    Html,
    Excel,
}

#[derive(Debug, Clone, Copy, ValueEnum, Default)]
enum SqlEnum {
    #[default]
    Mysql,
    Mssql,
}

impl From<SqlEnum> for SqlType {
    fn from(value: SqlEnum) -> Self {
        match value {
            SqlEnum::Mysql => SqlType::Mysql,
            SqlEnum::Mssql => SqlType::Mssql,
        }
    }
}

impl From<ExportEnum> for ExportType {
    fn from(value: ExportEnum) -> Self {
        match value {
            ExportEnum::Docx => Self::Docx,
            ExportEnum::Markdown => Self::Markdown,
            ExportEnum::Html => Self::Html,
            ExportEnum::Excel => Self::Excel,
        }
    }
}

impl Args {
    fn to_sql_config(&self) -> SqlConfig {
        let port = match self.r#type {
            SqlEnum::Mysql => 3306,
            SqlEnum::Mssql => 1433,
        };
        SqlConfig {
            host: self.host.clone(),
            port: self.port.unwrap_or(port),
            user: self.user.clone(),
            password: self.password.clone(),
            database: self.database.clone(),
            output: self.output.clone(),
        }
    }
}

#[tokio::main]
async fn main() {
    let args = Args::parse();
    let config = args.to_sql_config();
    let sql_type = args.r#type.into();
    let export = args.export.into();
    let result = run(sql_type, &config, export).await;
    result.map_or_else(
        |err| {
            eprintln!("错误:{:?}", err);
            eprintln!("发生错误:{}", err);
        },
        |path| println!("成功，文件保存在:{}", path),
    )
}
